--------------------------------------------------------
-- 跨服逻辑

-- 注意：跨服活动结束，返还操作列表给本服，不覆盖本服的DB！！！
--------------------------------------------------------

local Config 			= require("Config")
local CommonDefine		= require("common.CommonDefine")
local Log				= require("common.Log")
local Lang				= require("common.Lang")
local Util				= require("common.Util")
local CommonDB          = require("common.CommonDB")
local Msg				= require("core.Msg")
local InnerMsg			= require("core.InnerMsg")
local Obj				= require("core.Obj")
local ObjHuman			= require("core.ObjHuman")
local MiddleDefine		= require("middle.MiddleDefine")
local MiddleManager		= require("middle.MiddleManager")
local MiddleOption 		= require("middle.MiddleOption")
local MiddleConnect     = require("middle.MiddleConnect")
local Broadcast			= require("broadcast.Broadcast")
local MailLogic			= require("mail.MailLogic")
local MailManager       = require("mail.MailManager")
local BuyLogic			= require("topup.BuyLogic")
local RoleDBLogic       = require("role.RoleDBLogic")
local RoleAttr			= require("role.RoleAttr")

TRY_LOGIN_HUMAN = TRY_LOGIN_HUMAN or {} -- 尝试登陆跨服的human数据(存在这个表里的是还没有发CG_MIDDLE_LOGIN的)


-- 尝试进入跨服
function CG_MIDDLE_TRY_ENTER(human, msg)
	print("CG_MIDDLE_TRY_ENTER")

	if MiddleConnect.IS_MIDDLE_CONNECT ~= true then
		human.db.middleFlag = nil
		return Broadcast.sendErr(human, Lang.MIDDLE_SVR_ERR_CONNECT)
	end
	
	-- logic向middle传输玩家数据
	local msgSend = InnerMsg.lw.LW_TRY_ENTER_HUMAN
	msgSend.db = msgSend.db or {}
	msgSend.reason = msg.reason
	Util.cleanTable(msgSend.db)
	Util.copyTableSimple(human.db, msgSend.db)	

	-- 某些数据太大了，发到跨服会超出协议大小，所以不发 -- reyes todo 这里到时要确认有没有太大的db数据 选择性不发
	
	msgSend.pfInfo = msgSend.pfInfo or {}
	Util.cleanTable(msgSend.pfInfo)
	msgSend.pfInfo.region =	human.region
	msgSend.pfInfo.ip =	human.ip
	msgSend.pfInfo.pf =	human.pf
	msgSend.pfInfo.lang = human.lang
	msgSend.pfInfo.appid = human.appid
	msgSend.pfInfo.vopenid = human.vopenid
	msgSend.pfInfo.openkey = human.openkey
	msgSend.pfInfo.realSvrIndex = Config.SVR_INDEX
    msgSend.pfInfo.realSvrName = Config.SVR_NAME
		
	InnerMsg.sendMsg(0, msgSend) 
end

function checkEnterReason(reason)
	do return end
	if reason == MiddleDefine.MIDDLE_ENTER_REASON_1 then -- 
		return true
	end
end


function LW_TRY_ENTER_HUMAN(fd, msg)
	local db = msg.db	
	local pfInfo = msg.pfInfo
	local account = db.account
	local reason = msg.reason
	local retCode = MiddleDefine.MIDDLE_TRY_LOGIN_OK
	local msg = InnerMsg.wl.WL_TRY_ENTER_HUMAN
	msg.account = account
	
	local human = ObjHuman.onlineAccount[account]
	if human == nil then
		local onlineCnt = 0
		for k, v in pairs(ObjHuman.onlineAccount) do
			onlineCnt = onlineCnt + 1
		end
		if onlineCnt >= CommonDefine.MAX_ONLINE_COUNT then
			retCode = MiddleDefine.MIDDLE_TRY_LOGIN_ERR_FULL
			msg.retCode = retCode
			InnerMsg.sendMsg(fd, msg)	
			return
		end

		if not checkEnterReason(reason) then
			msg.retCode = MiddleDefine.MIDDLE_TRY_LOGIN_ACT_END
			InnerMsg.sendMsg(fd, msg)	
			return
		end
	
		if TRY_LOGIN_HUMAN[account] then
			-- 已经在尝试登陆列表中
			local tempData = TRY_LOGIN_HUMAN[account]
			Util.cleanTable(tempData.db)
			Util.copyTableSimple(db, tempData.db)
			
			Util.cleanTable(tempData.pfInfo)
			Util.copyTableSimple(pfInfo, tempData.pfInfo)
			
			tempData.tsForMiddle = os.time()
			tempData.reasonForMiddle = reason
			tempData.svrIndexForMiddle = MiddleManager.FD_2_SVRINDEX[fd]
		else
			local tempData = {}
			local newDB = {}
			Util.copyTableSimple(db, newDB)
			tempData.db = newDB
			
			local newPfInfo = {}
			Util.copyTableSimple(pfInfo, newPfInfo)
			tempData.pfInfo = newPfInfo
			
			tempData.tsForMiddle = os.time()
			tempData.reasonForMiddle = reason
			tempData.svrIndexForMiddle = MiddleManager.FD_2_SVRINDEX[fd]
			TRY_LOGIN_HUMAN[account] = tempData
		end
	else
		human.reasonForMiddle = reason
		human.svrIndexForMiddle = MiddleManager.FD_2_SVRINDEX[fd]
	end
	
	msg.retCode = retCode
	InnerMsg.sendMsg(fd, msg)
end

function WL_TRY_ENTER_HUMAN(fd, msg)
	local account = msg.account
	local retCode = msg.retCode
	
	local human = ObjHuman.onlineAccount[account]
	print("WL_TRY_ENTER_HUMAN",account, human, retCode)
	if human == nil then
		return
	end

	if retCode == MiddleDefine.MIDDLE_TRY_LOGIN_ERR_FULL then
		human.db.middleFlag = nil
		return Broadcast.sendErr(human, Lang.MIDDLE_SVR_ERR_FULL)
	elseif retCode == MiddleDefine.MIDDLE_TRY_LOGIN_ACT_END then
		human.db.middleFlag = nil
		return Broadcast.sendErr(human, Lang.MIDDLE_SVR_ERR_ACTEND)
	end
	
	if MiddleConnect.IS_MIDDLE_CONNECT ~= true then
		human.db.middleFlag = nil
		return Broadcast.sendErr(human, Lang.MIDDLE_SVR_ERR_CONNECT)
	end
	
	local ip, port, host = MiddleConnect.getMiddleInfo() 
	local msgRet = Msg.gc.GC_MIDDLE_TRY_ENTER
	msgRet.host = host
	Msg.send(msgRet, human.fd)
end

function CG_MIDDLE_LOGIN(fd, msg)
	if _G.is_middle ~= true then return end
		
	local account = msg.account
	print("CG_MIDDLE_LOGIN", account, param)
	local human = ObjHuman.onlineAccount[account]
	if human == nil then
		local tempData = TRY_LOGIN_HUMAN[account]
		if tempData == nil then
			return
		end
	
		TRY_LOGIN_HUMAN[account] = nil
	
		human = ObjHuman.create(fd, account, tempData.db)
		human.reasonForMiddle = tempData.reasonForMiddle
		human.svrIndexForMiddle = tempData.svrIndexForMiddle
		human.realSvrIndex = tempData.pfInfo.realSvrIndex
        human.realSvrName = tempData.pfInfo.realSvrName

		ObjHuman.doCalc(human)
	else
		-- 销毁老的 建新的
		if human.fd then 
			ObjHuman.fds[human.fd] = nil 
		end	
		ObjHuman.fds[fd] = human.id
		human.fd = fd
	end
	
	local reason = human.reasonForMiddle or 0	
	local msgRet = Msg.gc.GC_MIDDLE_LOGIN
	msgRet.param = reason
	Msg.send(msgRet, human.fd)
		
	print("middle has real human ", account, reason)

	--登录日志
	Log.write(Log.LOGID_OSS_LOGIN, human.db._id, human.db.account, human.db.name, human.db.lv, human.db.ip)	

	if not checkEnterReason(reason) then
		CG_MIDDLE_LOGOUT(human) -- 断开
		return
	end

	if reason == MiddleDefine.MIDDLE_ENTER_REASON_1 then	
		
	end
end

function CG_MIDDLE_LOGOUT(human)
	if _G.is_middle ~= true then return end
	
	local fd = MiddleManager.getFDBySvrIndex(human.svrIndexForMiddle)
	if not fd then
		Log.write(Log.LOGID_MIDDLE_BT, "CG_MIDDLE_LOGOUT:" .. (human.svrIndexForMiddle or 0))
		return 
	end
	
	Msg.send(Msg.gc.GC_MIDDLE_LOGOUT, human.fd)

	ObjHuman.doDisconnect(human, CommonDefine.DISCONNECT_NORMAL_AFTER, CommonDefine.DISCONNECT_MSG[CommonDefine.DISCONNECT_NORMAL_AFTER])
end

function sendWL_DB_BACK(human)
	local msgSend = InnerMsg.wl.WL_DB_BACK
	local fd = MiddleManager.getFDBySvrIndex(human.svrIndexForMiddle)
	if not fd then
		Log.write(Log.LOGID_MIDDLE_BT, "sendWL_DB_BACK:" .. (human.svrIndexForMiddle or 0))
		return 
	end
	msgSend.account = human.db.account
	msgSend.options = msgSend.options or {}
	Util.cleanTable(msgSend.options)
	if human.db.middleOptions then
		Util.copyTableSimple(human.db.middleOptions, msgSend.options)
		human.db.middleOptions = nil
	end	
	InnerMsg.sendMsg(fd, msgSend) 
end

local fakeHuman = {}
function WL_DB_BACK(fd, msg)
	local account = msg.account
	local options = msg.options
	
	local human = ObjHuman.onlineAccount[account]
	if human then
		human.db.middleFlag = nil
		BuyLogic.onLogin(human)
		MiddleOption.handleOptions(human, options) 
		ObjHuman.doCalc(human)	
		RoleDBLogic.saveRole(human.db)
	else
		local db = RoleDBLogic.getDbByAccount(account)
		if db then
			Util.cleanTable(fakeHuman)
			fakeHuman.db = db
			fakeHuman.db.middleFlag = nil
			fakeHuman.obj_type = Obj.TYPE_HUMAN
			RoleAttr.doCalc(fakeHuman)
			MiddleOption.handleOptions(fakeHuman, options)  
			RoleDBLogic.saveRole(fakeHuman.db)	
		else
			assert(nil, "ML_DB_BACK no this account " .. account)
		end
	end

	print("normal receive middle db and update")

end

-- 客户端告诉正常服 现在这个玩家在跨服玩ing
function CG_MIDDLE_PLAYING_STATUS(human, middleFlag)
	if _G.is_middle == true then return end

	human.db.middleFlag = middleFlag
	ObjHuman.save(human)
end

-- 发送mlmail通知
function sendWLMail(type,receiverUuid,title,content,items,senderName, svrIndex)
	local fd = MiddleManager.getFDBySvrIndex(svrIndex)
	if not fd then
		Log.write(Log.LOGID_DEBUG, "sendWLMail:" .. (svrIndex or 0))
		return 
	end
	
	local msgSend = InnerMsg.wl.WL_MAIL
	msgSend.type = type
	msgSend.receiverUuid = receiverUuid
	msgSend.title = title
	msgSend.content = content
	msgSend.items = items
	msgSend.senderName = senderName
    InnerMsg.sendMsg(fd, msgSend)
    return fd
end

-- middle通知logic发邮件/道具
function WL_MAIL(fd, msg)
	MailManager.add(msg.type, msg.receiverUuid,msg.title,msg.content,msg.items,msg.senderName)
end

function sendWLBroadcast(fd, uuid, lang)
    local msgRet = InnerMsg.wl.WL_BROADCAST
    msgRet.uuid = uuid
	msgRet.lang = lang
	InnerMsg.sendMsg(fd, msgRet)
	return true
end

-- 中心服务器结果
function WL_BROADCAST(fd, msg)
    local human = ObjHuman.onlineUuid[msg.uuid]
	if human == nil then
		return
	end
	Broadcast.sendErr(human, msg.lang) 
end


function LW_GM(fd, msg)
	local str = msg.gm
	local Gm = require("chat.Gm")
	
	local pos = string.find(str, " ", 1, true)
	local cmd = string.sub(str, 1, pos and pos - 1)
	
	if not Gm.d3[cmd] then
		return
	end
	
	local arg = string.sub(str, #cmd + 2)
	Gm.d3[cmd](nil, tonumber(arg) or arg)
end


function onLogin(human)
	if human.db.middleFlag == 0 then
		human.db.middleFlag = nil
	end

	if human.db.middleFlag == nil then
		return
	end

	local msg = {reason = human.db.middleFlag}
	CG_MIDDLE_TRY_ENTER(human, msg)
end